package com.useful.secure.utils;

import com.useful.core.constant.TokenConstant;
import com.useful.core.utils.Charsets;
import com.useful.core.utils.Func;
import com.useful.core.utils.WebUtil;
import com.useful.secure.entity.TokenInfo;
import com.useful.secure.entity.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.experimental.UtilityClass;

import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.security.Key;
import java.util.Base64;
import java.util.Date;
import java.util.Map;

/**
 * @author : wenchao.long
 * @date : Created in 2021/9/23 11:11 周四
 * @description :
 */
@UtilityClass
public class SecureUtil {

    private final String BASE64_SECURITY = Base64.getEncoder().encodeToString(TokenConstant.SIGN_KEY.getBytes(Charsets.UTF_8));
    private final String USER_ID = TokenConstant.USER_ID;
    private final String USER_NAME = TokenConstant.USER_NAME;
    private final String ROLE_NAME = TokenConstant.ROLE_NAME;

    public User getUser() {
        HttpServletRequest request = WebUtil.getRequest();
        if (request == null) {
            return null;
        }
        Claims claims = getClaims(request);
        if (claims == null) {
            return null;
        }
        Long userId = Func.toLong(claims.get(USER_ID));
        String username = Func.toStr(claims.get(USER_NAME));
        String roleName = Func.toStr(claims.get(ROLE_NAME));
        return User.builder()
                .userId(userId)
                .username(username)
                .roleName(roleName)
                .build();
    }

    /**
     * 获取用户id
     *
     * @return Id
     */
    public Long getUserId() {
        User user = getUser();
        return user == null ? -1 : user.getUserId();
    }

    /**
     * 获取用户名
     *
     * @return String
     */
    public String getUserName() {
        User user = getUser();
        return user == null ? "" : user.getUsername();
    }

    /**
     * 获取getClaims
     *
     * @param request request
     * @return request
     */
    public Claims getClaims(HttpServletRequest request) {
        String token = request.getHeader(TokenConstant.TOKEN);
        return Func.isNotBlank(token) ? parseJwt(token) : null;
    }

    /**
     * 解析token
     *
     * @param token token
     * @return Claims
     */
    public Claims parseJwt(String token) {
        try {
            return Jwts.parserBuilder()
                    .setSigningKey(Base64.getDecoder().decode(BASE64_SECURITY))
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception ex) {
            return null;
        }
    }

    /**
     * 创建token令牌
     *
     * @param user user
     * @return TokenInfo
     */
    public TokenInfo createToken(Map<String, String> user) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        // 生成签名秘钥
        byte[] apiKeySecretBytes = Base64.getDecoder().decode(BASE64_SECURITY);
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

        // 构成JWT
        JwtBuilder builder = Jwts.builder().setHeaderParam("type", "JWT")
                .setIssuer("issuer")
                .setAudience("audience")
                .signWith(signingKey);

        user.forEach(builder::claim);

        // 添加token过期时间
        long expireMillis;
        expireMillis = 24 * 3600 * 1000;
        builder.setExpiration(new Date(nowMillis + expireMillis))
                .setNotBefore(now);

        TokenInfo tokenInfo = new TokenInfo();
        tokenInfo.setToken(builder.compact());
        tokenInfo.setExpire((int) expireMillis / 1000);

        return tokenInfo;
    }

}
